wayland: Add API for setting an exported as a parent
authorJonas Ådahl <jadahl@gmail.com>
Wed, 13 Jul 2016 07:24:19 +0000 (15:24 +0800)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 29 Aug 2016 17:20:44 +0000 (13:20 -0400)
Add an API that enables an application to, given an exported window
handle, set its own window as a transient of the window associated with
the exported window handle.

https://bugzilla.gnome.org/show_bug.cgi?id=769788

gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdkwaylandwindow.h
gdk/wayland/gdkwindow-wayland.c

index 4bb247e16041fefeba6d999313bb7f535bc2debd..3566d69fbe3a037e6c9cfeb9a502e5976e175cd6 100644 (file)
@@ -440,6 +440,12 @@ gdk_registry_handle_global (void               *data,
         wl_registry_bind (display_wayland->wl_registry, id,
                           &zxdg_exporter_v1_interface, 1);
     }
+  else if (strcmp (interface, "zxdg_importer_v1") == 0)
+    {
+      display_wayland->xdg_importer =
+        wl_registry_bind (display_wayland->wl_registry, id,
+                          &zxdg_importer_v1_interface, 1);
+    }
   else
     handled = FALSE;
 
index f21e8b631b05954fd227f033e4fa0e91c473366b..ace514349d1e595c816317b1e53c1e9ca04b6f36 100644 (file)
@@ -76,6 +76,7 @@ struct _GdkWaylandDisplay
   struct gtk_primary_selection_device_manager *primary_selection_manager;
   struct zwp_tablet_manager_v2 *tablet_manager;
   struct zxdg_exporter_v1 *xdg_exporter;
+  struct zxdg_importer_v1 *xdg_importer;
 
   GList *async_roundtrips;
 
index 6c006e80a7136b46f6a7f500c2483a58731ddcab..566d40524c40e16676efd5925a3992cd549b1731 100644 (file)
@@ -73,6 +73,10 @@ gboolean                 gdk_wayland_window_export_handle (GdkWindow
 GDK_AVAILABLE_IN_3_22
 void                     gdk_wayland_window_unexport_handle (GdkWindow *window);
 
+GDK_AVAILABLE_IN_3_22
+gboolean                 gdk_wayland_window_set_transient_for_exported (GdkWindow *window,
+                                                                        char      *parent_handle_str);
+
 G_END_DECLS
 
 #endif /* __GDK_WAYLAND_WINDOW_H__ */
index fe11d943e01806146a69097220f1964ca852caa2..e8769f7a7749b72a360de14e83785f67091733e5 100644 (file)
@@ -203,6 +203,8 @@ struct _GdkWindowImplWayland
     gpointer user_data;
     GDestroyNotify destroy_func;
   } exported;
+
+  struct zxdg_imported_v1 *imported_transient_for;
 };
 
 struct _GdkWindowImplWaylandClass
@@ -224,6 +226,8 @@ static void gdk_wayland_window_sync_margin (GdkWindow *window);
 static void gdk_wayland_window_sync_input_region (GdkWindow *window);
 static void gdk_wayland_window_sync_opaque_region (GdkWindow *window);
 
+static void unset_transient_for_exported (GdkWindow *window);
+
 GType _gdk_window_impl_wayland_get_type (void);
 
 G_DEFINE_TYPE (GdkWindowImplWayland, _gdk_window_impl_wayland, GDK_TYPE_WINDOW_IMPL)
@@ -2321,6 +2325,8 @@ gdk_wayland_window_hide_surface (GdkWindow *window)
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
 
+  unset_transient_for_exported (window);
+
   if (impl->display_server.wl_surface)
     {
       if (impl->dummy_egl_surface)
@@ -2983,6 +2989,8 @@ gdk_wayland_window_set_transient_for (GdkWindow *window,
       return;
     }
 
+  unset_transient_for_exported (window);
+
   if (impl->display_server.wl_subsurface)
     unmap_subsurface (window);
 
@@ -3915,3 +3923,65 @@ gdk_wayland_window_unexport_handle (GdkWindow *window)
   g_clear_pointer (&impl->exported.user_data,
                    impl->exported.destroy_func);
 }
+
+static void
+unset_transient_for_exported (GdkWindow *window)
+{
+  GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+
+  g_clear_pointer (&impl->imported_transient_for, zxdg_imported_v1_destroy);
+}
+
+static void
+xdg_imported_destroyed (void                    *data,
+                        struct zxdg_imported_v1 *zxdg_imported_v1)
+{
+  GdkWindow *window = data;
+
+  unset_transient_for_exported (window);
+}
+
+static const struct zxdg_imported_v1_listener xdg_imported_listener = {
+  xdg_imported_destroyed,
+};
+
+/**
+ * gdk_wayland_window_set_transient_for_exported:
+ *
+ * Stability: unstable
+ */
+gboolean
+gdk_wayland_window_set_transient_for_exported (GdkWindow *window,
+                                               char      *parent_handle_str)
+{
+  GdkWindowImplWayland *impl;
+  GdkWaylandDisplay *display_wayland;
+  GdkDisplay *display = gdk_window_get_display (window);
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
+
+  impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  display_wayland = GDK_WAYLAND_DISPLAY (display);
+
+  g_return_val_if_fail (impl->display_server.xdg_surface, FALSE);
+
+  if (!display_wayland->xdg_importer)
+    {
+      g_warning ("Server is missing xdg_foreign support");
+      return FALSE;
+    }
+
+  gdk_window_set_transient_for (window, NULL);
+
+  impl->imported_transient_for =
+    zxdg_importer_v1_import (display_wayland->xdg_importer, parent_handle_str);
+  zxdg_imported_v1_add_listener (impl->imported_transient_for,
+                                 &xdg_imported_listener,
+                                 window);
+
+  zxdg_imported_v1_set_parent_of (impl->imported_transient_for,
+                                  impl->display_server.wl_surface);
+
+  return TRUE;
+}